package cn.kai.basic.aop;

import cn.kai.basic.anno.LogAnno;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;


@Component // 交给spring管理
@Slf4j
@Aspect // 切面，定义了通知和切点的关系
public class LogAop {
    /**
     * 定义一个空方法
     */
    @Pointcut("@annotation(cn.kai.basic.anno.LogAnno)")
    public void pointCut(){}


    //环绕通知
    @Around("pointCut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        // 开始时间
        long currentTime = System.currentTimeMillis();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy年-MM月dd日-HH时mm分ss秒");
        Date date = new Date(currentTime);
        String time = formatter.format(date);
        long beginTime = System.currentTimeMillis();

        // 执行时间
        long endTime = System.currentTimeMillis() - beginTime;
        recordLog(pjp,endTime,time);

        //执行业务方法
        //这里必须得返回一个Object值，这个值是在controller执行时后端返回的
        //因为用了环切，在controller执行完成后该数据被拦截
        //需要.proceed();方法获取对象，再返回值给前端
        Object proceed = pjp.proceed();
        return proceed;
    }

    private void recordLog(ProceedingJoinPoint pjp,Long endTime,String time) throws UnknownHostException {
        //获取所有方法
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        LogAnno annotation = method.getAnnotation(LogAnno.class);
        log.info("-----------------log show-------------------");
        log.info("method:{}",annotation.method());
        log.info("methodDes:{}",annotation.methodDes());
        log.info("start time:{}",time);
        //请求的方法名
        String className = pjp.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.info("request method:{}",className+"."+methodName);

        //添加或者修改的方法
        Object[] args = pjp.getArgs();
        log.info("params:{}", Arrays.toString(args));

        // 获取ip地址
        InetAddress localHost = InetAddress.getLocalHost();
        String ipAddress = localHost.getHostAddress();
        log.info("ip:{}", ipAddress);
        log.info("excute:{} ms",endTime);
        log.info("===============log end ===============");

    }
}
